﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace AdvanceLib.UI
{
    public class Animator
    {
        #region Constructors
        public Animator()
        {
            this._animations = new Dictionary<string, Animation>();
        }
        #endregion

        #region Fields
        private Dictionary<string, Animation> _animations;

        private string _lastAnimationName;
        #endregion

        #region Events
        public event EventHandler AnimateFrame;
        #endregion

        #region Methods
        public void AddAnimation(string animationName, Animation animation)
        {
            this._animations.Add(animationName, animation);
        }
        public void AddAnimation(string animationName, int duration)
        {
            this._animations.Add(animationName, new Animation(duration));
        }
        public void AddAnimation(string animationName, int duration, int frameRate)
        {
            this._animations.Add(animationName, new Animation(duration, frameRate));
        }
        public float GetValue(string animationName)
        {
            if (this._animations.ContainsKey(animationName))
            {
                return this._animations[animationName].Value;
            }
            return 0.0f;
        }
        public void Animate(string animationName)
        {
            this._lastAnimationName = animationName;

            Thread animationThread = new Thread(AnimateThread);
            animationThread.Start();
        }
        public void Animate(string animationName, AnimationDirection direction)
        {
            Animation animation = this._animations[animationName];
            animation.Direction = direction;

            Animate(animationName);
        }
        private void AnimateThread()
        {
            Animation animation = this._animations[this._lastAnimationName];

            while ((animation.Direction == AnimationDirection.Increment && animation.Value < 1.0f) ||
                   (animation.Direction == AnimationDirection.Decrement && animation.Value > 0.0f))
            {
                float value = animation.Value;
                float step = (float)(1000 / animation.FrameRate);

                switch (animation.Direction)
                {
                    case AnimationDirection.Increment:
                        value = animation.Value + (1.0f / (float)animation.Duration) * step;
                        animation.Value = Math.Min(value, 1.0f);
                        break;
                    case AnimationDirection.Decrement:
                        value = animation.Value - (1.0f / (float)animation.Duration) * (1000 / animation.FrameRate);
                        animation.Value = Math.Max(value, 0.0f);
                        break;
                }
                OnAnimateFrame();

                Thread.Sleep(1000 / animation.FrameRate);
            }
        }
        private void OnAnimateFrame()
        {
            if (this.AnimateFrame != null)
            {
                this.AnimateFrame.Invoke(this, new EventArgs());
            }
        }
        #endregion
    }
}
